package main

import (
        "fmt"
        "os"
        "syscall"
        "unsafe"
        . "code.google.com/p/draw2d/wingui"
)

// some help functions

func abortf(format string, a ...interface{}) {
        fmt.Fprintf(os.Stdout, format, a...)
        os.Exit(1)
}

func abortErrNo(funcname string, err error) {
        errno, _ := err.(syscall.Errno)
        abortf("%s failed: %d %s\n", funcname, uint32(errno), err)
}

// global vars

var (
        mh syscall.Handle
        bh syscall.Handle
)

// WinProc called by windows to notify us of all windows events we might be interested in.
func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
		_ = make([]int, 100000)
        switch msg {
        case WM_CREATE:
                var e error
                // CreateWindowEx
                bh, e = CreateWindowEx(
                        0,
                        syscall.StringToUTF16Ptr("button"),
                        syscall.StringToUTF16Ptr("Quit"),
                        WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
                        75, 70, 140, 25,
                        hwnd, 1, mh, 0)
                if e != nil {
                        abortErrNo("CreateWindowEx", e)
                }
                fmt.Printf("button handle is %x\n", bh)
                rc = DefWindowProc(hwnd, msg, wparam, lparam)
        case WM_COMMAND:
                switch syscall.Handle(lparam) {
                case bh:
                        e := PostMessage(hwnd, WM_CLOSE, 0, 0)
                        if e != nil {
                                abortErrNo("PostMessage", e)
                        }
                default:
                        rc = DefWindowProc(hwnd, msg, wparam, lparam)
                }
        case WM_CLOSE:
                DestroyWindow(hwnd)
        case WM_DESTROY:
                PostQuitMessage(0)
        default:
                rc = DefWindowProc(hwnd, msg, wparam, lparam)
        }
        //fmt.Printf("WndProc(0x%08x, %d, 0x%08x, 0x%08x) (%d)\n", hwnd, msg, wparam, lparam, rc)
        return
}

func rungui() int {
        var e error

        // GetModuleHandle
        mh, e = GetModuleHandle(nil)
        if e != nil {
                abortErrNo("GetModuleHandle", e)
        }

        // Get icon we're going to use.
        myicon, e := LoadIcon(0, IDI_APPLICATION)
        if e != nil {
                abortErrNo("LoadIcon", e)
        }

        // Get cursor we're going to use.
        mycursor, e := LoadCursor(0, IDC_ARROW)
        if e != nil {
                abortErrNo("LoadCursor", e)
        }

        // Create callback
        wproc := syscall.NewCallback(WndProc)

        // RegisterClassEx
        wcname := syscall.StringToUTF16Ptr("myWindowClass")
        var wc Wndclassex
        wc.Size = uint32(unsafe.Sizeof(wc))
        wc.WndProc = wproc
        wc.Instance = mh
        wc.Icon = myicon
        wc.Cursor = mycursor
        wc.Background = COLOR_BTNFACE + 1
        wc.MenuName = nil
        wc.ClassName = wcname
        wc.IconSm = myicon
        if _, e := RegisterClassEx(&wc); e != nil {
                abortErrNo("RegisterClassEx", e)
        }

        // CreateWindowEx
        wh, e := CreateWindowEx(
                WS_EX_CLIENTEDGE,
                wcname,
                syscall.StringToUTF16Ptr("My window"),
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
                0, 0, mh, 0)
        if e != nil {
                abortErrNo("CreateWindowEx", e)
        }
        fmt.Printf("main window handle is %x\n", wh)

        // ShowWindow
        ShowWindow(wh, SW_SHOWDEFAULT)

        // UpdateWindow
        if e := UpdateWindow(wh); e != nil {
                abortErrNo("UpdateWindow", e)
        }

        // Process all windows messages until WM_QUIT.
        var m Msg
        for {
                r, e := GetMessage(&m, 0, 0, 0)
                if e != nil {
                        abortErrNo("GetMessage", e)
                }
                if r == 0 {
                        // WM_QUIT received -> get out
                        break
                }
                TranslateMessage(&m)
                DispatchMessage(&m)
        }
        return int(m.Wparam)
}

func main() {
        rc := rungui()
        os.Exit(rc)
}
